package com.swf.common.utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.swf.common.base.FwsCharset;


/**
 * description:字符串IO流工具，其中inFile，inPath,is只有最后一个设置有用，outPath，outFile只有最后一个设置有用
 * @version 1.0 2013-6-20
 * @author shenwf
 */
public class FwsIOUtils{
	
	/**
	 * 输入文件
	 */
	private File  inFile; 
	/**
	 * 输入文件路径
	 */
	private String inPath;
	/**
	 * 输入字节流
	 */
	private InputStream is;
	/**
	 * 字符编码 ，默认当前系统编码
	 */
	private String charst = FwsCharset.defaultCharset;
	
	/**
	 * 输出文件
	 */
	private File outFile;
	/**
	 * 输入文件
	 */
	private String outPath;
	/**
	 * 输出流
	 */
	private OutputStream os;
	/**
	 * 输出内容
	 */
	private String content;
	/**
	 * 是否追加到文件,默认不追加
	 */
	private boolean append = false;
	
	/**
	 * 文件当前行，current LineNumber; 
	 */
	private int currentLineNumber = 0;
	/**
	 * 跳过行数
	 */
	private int skipLineNumber = 0;
	/**
	 * 读取文件的位置 
	 */
	private long position = 0L;
	/**
	 * 文件读取当前的位置 
	 */
	private long currentPosition = 0L;
	/**
	 * 随机读写文件对象实例
	 */
	private RandomAccessFile raf;
	/**
	 * 随机读写对象模式,默认为rw
	 */
	private String rafMode = "rw";
	
	
	
	private static Logger logger = LoggerFactory
			.getLogger(FwsIOUtils.class);
	
	
	/**
	 * 默认构造器
	 */
	public FwsIOUtils() {
	}
	
	public static FwsIOUtils getInstance(){
		return new FwsIOUtils();
	}
	
	public void setSkipLineNumber(int skipLineNumber) {
		this.skipLineNumber = skipLineNumber;
	}

	public File getInFile() {
		return inFile;
	}


	public FwsIOUtils setInFile(File inFile) {
		this.inFile = inFile;
		this.is = null;
		this.inPath = null;
		try {
			raf = new RandomAccessFile(inFile, rafMode);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return this;
	}


	public String getInPath() {
		return inPath;
	}


	public FwsIOUtils setInPath(String inPath) {
		this.inPath = inPath;
		this.inFile = null;
		this.is = null;
		try {
			raf = new RandomAccessFile(inPath, rafMode);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return this;
	}

	
	public InputStream getIs() {
		return is;
	}


	public FwsIOUtils setIs(InputStream is) {
		this.is = is;
		this.inPath = null;
		this.inFile = null;
		return this;
	}


	public String getCharst() {
		return charst;
	}


	public FwsIOUtils setCharst(String charst) {
		this.charst = charst;
		return this;
	}


	public File getOutFile() {
		return outFile;
	}


	public FwsIOUtils setOutFile(File outFile) {
		this.outFile = outFile;
		this.outPath = null;
		this.os = null;
		return this;
	}


	public String getOutPath() {
		return outPath;
	}

	
	public OutputStream getOs() {
		return os;
	}


	public FwsIOUtils setOs(OutputStream os) {
		this.os = os;
		this.outFile = null;
		this.outPath = null;
		return this;
	}


	public FwsIOUtils setOutPath(String outPath) {
		this.outPath = outPath;
		this.outFile = null;
		this.os = null;
		return this;
	}


	public String getContent() {
		return content;
	}


	public FwsIOUtils setContent(String content) {
		this.content = content;
		return this;
	}


	public boolean isAppend() {
		return append;
	}


	public FwsIOUtils setAppend(boolean append) {
		this.append = append;
		return this;
		
	}
	
	public int getCurrentLineNumber() {
		return currentLineNumber;
	}

	public long getCurrentPosition() {
		return currentPosition;
	}

	public void setPosition(long position) {
		this.position = position;
	}

	
	/**
	 * read whole file content
	 * @return
	 * @throws IOException
	 */
	public String read() throws IOException{
		if (inPath!=null) {
			inFile = FwsFileUtils.getFile(inPath);
		}
		if (inFile!=null){
		    is = new FileInputStream(inFile);
		} 
		if (is==null){
			logger.error("请设置输入路径或文件！");
			return null;
		}
		
		InputStreamReader isr = new InputStreamReader(is,charst);
		BufferedReader br = new BufferedReader(isr);
		char[] cbuf = new char[1024];
		StringBuffer sb = new StringBuffer();
		int len;
		while ((len=br.read(cbuf))!=-1){
			sb.append(cbuf,0,len);
		}
		return sb.toString();
	}
	
	/**
	 * read file by line
	 * @return
	 * @throws IOException
	 */
	public List<String> readByLine() throws IOException{
		List<String> list = new LinkedList<String>();
		if (inPath!=null) {
			inFile = FwsFileUtils.getFile(inPath);
		}
		if (inFile!=null){
		    is = new FileInputStream(inFile);
		} 
		if (is==null){
			logger.error("请设置输入路径或文件！");
			return null;
		}
		
		InputStreamReader isr = new InputStreamReader(is,charst);
		BufferedReader br = new BufferedReader(isr);
		String line = null;
		int lineNumber = 0;
		while ((line = br.readLine())!=null){
			if (++lineNumber>this.skipLineNumber){
				list.add(line);
			}
		}
		this.currentLineNumber = lineNumber;
		return list;
	}
	
	
	/**
	 * write content to file
	 * @throws IOException
	 */
	public void write() throws IOException{
		if (outPath!=null){
			outFile = new File(outPath);
		}
		if (outFile!=null){
			os = new FileOutputStream(outFile,append);
		}
		if (os==null){
			logger.error("请设置输出路径或文件！");
			return;
		}
		
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, charst));
		bw.write(content);
		bw.flush();
		bw.close();
	}
	
	/**
	 * write content to file and newLine
	 * @throws IOException
	 */
	public void writeByline() throws IOException{
		if (outPath!=null){
			outFile = new File(outPath);
		}
		if (outFile!=null){
			os = new FileOutputStream(outFile,append);
		}
		if (os==null){
			logger.error("请设置输出路径或文件！");
			return;
		}
		
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, charst));
		bw.write(content);
		bw.newLine();
		bw.flush();
		bw.close();
	}
	
	
	public List<String> readRandom() throws IOException{
		List<String> list = new ArrayList<String>();
		RandomAccessFile randomAccessFile = new RandomAccessFile(inFile, "r");
		randomAccessFile.seek(this.position);
		String line = null;
		int lineNumber=0;
		while ((line=randomAccessFile.readLine())!=null){
			if (++lineNumber>this.skipLineNumber){
			list.add(new String(line.getBytes(FwsCharset.ISO_8859_1),charst));
			}
		}
		this.currentLineNumber = lineNumber;
		this.currentPosition = randomAccessFile.getFilePointer();
		return list;
	}
	
	public String readRandomLine() throws IOException{
		this.raf.seek(this.position);
		String line=raf.readLine();
		this.currentPosition = this.raf.getFilePointer();
		return line==null?"":new String(line.getBytes(FwsCharset.ISO_8859_1),charst);
	}
	
	public boolean hasNextLine() throws IOException{
		return currentPosition<raf.getFilePointer();
	}
}
